package crons

import (
	"context"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/shopspring/decimal"
	"hotgo/internal/consts"
	"hotgo/internal/dao"
	"hotgo/internal/library/cron"
	"hotgo/internal/model/entity"
	"hotgo/internal/model/input/sysin"
	"hotgo/internal/service"
	"time"
)

// 每天凌晨生成竞拍场次
func init() {
	cron.Register(AuctionWaitStart)
}

var AuctionWaitStart = &cAuctionWaitStart{name: "auction_wait_start"}

type cAuctionWaitStart struct {
	name string
}

func (c *cAuctionWaitStart) GetName() string {
	return c.name
}

// Execute 执行任务
func (c *cAuctionWaitStart) Execute(ctx context.Context, parser *cron.Parser) (err error) {
	// 业务逻辑
	var (
		auctionList []entity.Auction
	)
	// 查询可用竞拍活动
	if err = service.SysAuction().Model(ctx).
		Where(dao.Auction.Columns().Enabled, true).
		WhereLTE(dao.Auction.Columns().StartDate, gtime.Now()).
		WhereGTE(dao.Auction.Columns().EndDate, gtime.Now()).
		Scan(&auctionList); err != nil {
		parser.Logger.Warning(ctx, "cron AuctionStart Execute err: ", err)
		return
	}
	if len(auctionList) == 0 {
		parser.Logger.Info(ctx, "cron AuctionStart Execute no data")
		return
	}
	// 查询对应的商品
	for _, auction := range auctionList {
		err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
			var mapperList []*entity.AuctionProductMapper
			if err = service.SysAuctionProductMapper().Model(ctx).
				Where(dao.AuctionProductMapper.Columns().AuctionId, auction.Id).
				Where(dao.AuctionProductMapper.Columns().Status, consts.AuctionStatusEnd).
				Where("JSON_CONTAINS(`weekday`, ?)", gconv.String(int(gtime.Now().Weekday()))).
				Scan(&mapperList); err != nil {
				parser.Logger.Warning(ctx, "cron AuctionStart Execute err: ", err)
				return err
			}

			for _, mapper := range mapperList {
				if _, err = service.SysAuctionProductMapper().Model(ctx).
					Data(g.Map{
						dao.AuctionProductMapper.Columns().Status: consts.AuctionStatusWaitStart,
					}).
					WherePri(mapper.Id).
					Update(); err != nil {
					parser.Logger.Warning(ctx, "cron AuctionStart Execute err: ", err)
					return err
				}
				logActiveTime := mapper.EndTime.Sub(mapper.StartTime).Seconds() / float64(mapper.Count)
				startT := mapper.StartTime
				endT := new(gtime.Time)
				for i := 0; i < mapper.Count; i++ {
					endT = startT.Add(time.Duration(logActiveTime) * time.Second)
					if _, err = service.SysAuctionLog().Model(ctx).Data(&sysin.AuctionLogEditInp{
						AuctionLog: entity.AuctionLog{
							AuctionId:            auction.Id,
							MapperId:             mapper.Id,
							ProductId:            mapper.ProductId,
							FinalPrice:           decimal.NewFromInt(0).InexactFloat64(),
							Date:                 gtime.Now(),
							StartTime:            startT,
							EndTime:              endT,
							NumberOfParticipants: 0,
							Status:               consts.AuctionLogWaitStart,
							BidLog:               gjson.New([]interface{}{}),
						},
					}).InsertAndGetId(); err != nil {
						parser.Logger.Warning(ctx, "cron AuctionStart Execute err: ", err)
						return err
					}
					startT = endT.Add(time.Duration(logActiveTime))
				}

			}
			return nil
		})
		if err != nil {
			parser.Logger.Warning(ctx, "cron AuctionStart Execute err: ", err)
			continue
		}
	}
	return
}
